import type {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig
} from 'axios'
import axios, { AxiosError } from 'axios'
import { notification } from 'ant-design-vue/lib/components'
import { clearToken, getToken, isLogin } from '@/utils/auth'
import router from '@/router'
import { message } from 'ant-design-vue'

type Result<T> = {
  code: number
  msg: string
  data: T
}

// 导出Request类，可以用来自定义传递配置来创建实例
export class Request {
  // axios 实例
  instance: AxiosInstance

  constructor(config: AxiosRequestConfig) {
    // 使用axios.create创建axios实例
    this.instance = axios.create(config)

    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        if ((config.method === 'get' || config.method === 'delete') && config.params) {
          // 重新编码
          let url = config.url + '?' + tansParams(config.params)
          url = url.slice(0, -1)
          config.params = {}
          config.url = url
        }
        // 一般会请求拦截里面加token，用于后端的验证
        if (isLogin()) {
          const token = getToken()
          if (token) {
            config.headers!.Authorization = token
          }
        }
        return config
      },
      (err: any) => {
        // 请求错误，这里可以用全局提示框进行提示
        return Promise.reject(err)
      }
    )

    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        // 直接返回res，当然你也可以只返回res.data
        // 系统如果有自定义code也可以在这里处理
        if (response.data.code !== 200) {
          switch (response.data.code) {
            case 401: {
              clearToken()
              router.push('/login').then(() => message.warn('请重新登录'))
              break
            }
            case 403: {
              message
                .warn('权限不足，不要试图搞事情！！！')
                .then(() => message.info('如果更新了权限，请重新登录'))
            }
          }
        }
        return response
      },
      (error: AxiosError) => {
        // 这里错误消息可以使用全局弹框展示出来
        notification.error({
          message: error.code,
          description: error.message,
          onClick: () => {
            console.log('Notification Clicked!')
          }
        })
        return Promise.reject(error)
      }
    )
  }

  // 定义请求方法
  public request(config: AxiosRequestConfig): Promise<AxiosResponse> {
    return this.instance.request(config)
  }

  public get<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<Result<T>>> {
    return this.instance.get(url, config)
  }

  public post<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<Result<T>>> {
    return this.instance.post(url, data, config)
  }

  public put<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<Result<T>>> {
    return this.instance.put(url, data, config)
  }

  public delete<T = any>(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<Result<T>>> {
    return this.instance.delete(url, config)
  }
}

export const request = new Request({
  // baseURL: 'http://192.168.7.61:9901',
  // baseURL: 'http://127.0.0.1:9901',
  // baseURL: 'http://47.120.9.98:9901',
  timeout: 60000
})

/**
 * 参数处理[对象转参数 || 参数转义]
 * @param params 参数
 */
export function tansParams(params: { [x: string]: any }) {
  let result = ''
  for (const propName of Object.keys(params)) {
    const value = params[propName]
    const part = encodeURIComponent(propName) + '='
    if (value !== null && value !== '' && typeof value !== 'undefined') {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
            // let params = propName + '[' + key + ']'
            const subPart = encodeURIComponent(propName) + '='
            result += subPart + encodeURIComponent(value[key]) + '&'
          }
        }
      } else {
        result += part + encodeURIComponent(value) + '&'
      }
    }
  }
  return result
}
